package com.cloudclassroom.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.*;

/**
 * @author 92110
 */
@SuppressWarnings("all")
public class JwtUtils {
    /**
     * 密钥
     */
    private static final String KEY = "47385650444543446354357A4D6C53447838346F6364425A6B7837776B466A36";
    /**
     * 黑名单
     */
    private static final HashSet<String> blackList = new HashSet<>();

    /**
     * 创建JWT令牌
     * @param user 用户信息
     * @return JWT令牌
     */
    public static String createJwt(User user){
        Algorithm algorithm = Algorithm.HMAC256(KEY);
        Calendar calendar = Calendar.getInstance();
        Date now = calendar.getTime();
        calendar.add(Calendar.SECOND, 3600 * 24 * 7);
        return JWT.create()
                .withJWTId(UUID.randomUUID().toString())
                //配置JWT自定义信息
                .withClaim("name", user.getUsername())
                .withClaim("authorities", user.getAuthorities().stream()
                        .map(GrantedAuthority::getAuthority).toList()
                )
                //设置过期时间
                .withExpiresAt(calendar.getTime())
                //设置创建创建时间
                .withIssuedAt(now)
                //最终签名
                .sign(algorithm);
    }

    /**
     * 解析JWT令牌
     * @param token JWT令牌
     * @return 用户信息
     */
    public static UserDetails resolveJwt(String token){
        Algorithm algorithm = Algorithm.HMAC256(KEY);
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        try {
            DecodedJWT verify = jwtVerifier.verify(token);
            //判断是否存在于黑名单中，如果存在，则返回null表示失效
            if(blackList.contains(verify.getId()))
                return null;
            Map<String, Claim> claims = verify.getClaims();
            if(new Date().after(claims.get("exp").asDate()))
                return null;
            return User
                    .withUsername(claims.get("name").asString())
                    .password("")
                    .authorities(claims.get("authorities").asArray(String.class))
                    .build();
        } catch (JWTVerificationException e) {
            return null;
        }
    }

    /**
     * 失效JWT令牌
     * @param token JWT令牌
     * @return 是否失效
     */
    public static boolean invalidate(String token){
        Algorithm algorithm = Algorithm.HMAC256(KEY);
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        try {
            DecodedJWT verify = jwtVerifier.verify(token);
            Map<String, Claim> claims = verify.getClaims();
            //取出UUID丢进黑名单中
            return blackList.add(verify.getId());
        } catch (JWTVerificationException e) {
            return false;
        }
    }
}
